use std::{
    collections::HashMap,
    fs::File,
    io::{BufReader, Read},
};

use container_core::workflow::{SimpleWorkflowEngine, SomeChainsBuilder};
use datasource_connector::connector::SimpleDataSourceConnector;
use model_graph_types::{
    application::{
        agent::{
            AgentChatRequestMessage, AgentChatResponseMessage, AgentChatResponseMessageBuilder,
            AgentChatResponseMessageItemBuilder,
        },
        ApplicationHandler, FetchOptions,
    },
    assistant::prompts::{PromptTemplateItemBuilder, ASSISTANT_ROLE_KEY, USER_ROLE_KEY},
    container::workflow::{WorkflowEngine, WorkflowEngineRunOptionsBuilder,WorkflowModel,WorkflowModelBuilder},
    database::{ConnectorProtocol, DataSource, DataSourceBuilder, DatabaseType},
    datasource::{DataSourceConnector, QueryCondition},
    modeling::{
        application::InstalledApplication, system_meta_database, workspace::ProjectApplication,
        ClassGetter,
    },
};

use crate::config::{ApplicationDocument, ApplicationModelConfig};

#[derive(Debug)]
pub struct SimpleApplicationHandler {
    //
    pub application_identifier: String,
    //
    pub model_config: ApplicationModelConfig,
    //
    pub datasource: Option<DataSource>,
}

impl SimpleApplicationHandler {
    pub async fn new(identifier: &String, is_installed: bool) -> anyhow::Result<Self> {
        let ds = system_meta_database()?;
        //判断是本地应用，还是工程中的应用
        let (config_file, datasource) = if is_installed {
            let application: InstalledApplication = SimpleDataSourceConnector::default()
                .instance_query_one(
                    &None,
                    &ds,
                    &InstalledApplication::get_identifier()?,
                    QueryCondition::with_attribute(String::from("identifier"), identifier.clone())?,
                    None,
                    None,
                )
                .await?
                .try_into()?;

            //安装路径，由安装路径获取到配置文件的路径
            (
                application.installed_path.clone(),
                application.datasource.clone(),
            )
        } else {
            let application: ProjectApplication = SimpleDataSourceConnector::default()
                .instance_query_one(
                    &None,
                    &ds,
                    &ProjectApplication::get_identifier()?,
                    QueryCondition::with_attribute(String::from("identifier"), identifier.clone())?,
                    None,
                    None,
                )
                .await?
                .try_into()?;

            (
                application.path.map_or(
                    Err(anyhow::anyhow!("没有找到应用的配置文件")),
                    |path| Ok(path),
                )?,
                application.datasource.clone(),
            )
        };

        //读取配置文件，并加载配置
        let content = {
            let file = File::open(config_file)?;
            let mut buf_reader = BufReader::new(file);
            // 解析配置文件
            let mut content = String::new();
            buf_reader.read_to_string(&mut content)?;
            content
        };
        //解析配置文件
        let document: ApplicationDocument = serde_json::from_str(content.as_str())
            .map_err(|err| anyhow::anyhow!("应用文件json解析失败:{}", err))?;

        let datasource_option = if let Some(ds) = datasource {
            if ds.starts_with("{") {
                //json
                let ds_object: DataSource =
                    serde_json::from_str(ds.as_str()).map_err(|err| anyhow::anyhow!("{}", err))?;
                Some(ds_object)
            } else {
                // url
                Some(
                    DataSourceBuilder::default()
                        .database_type(DatabaseType::SQLite)
                        .protocol(ConnectorProtocol::SQLite)
                        .url(ds)
                        .build()?,
                )
            }
        } else {
            None
        };
        //
        Ok(Self {
            application_identifier: identifier.clone(),
            model_config: document.model_config,
            datasource: datasource_option,
        })
    }
}

#[async_trait::async_trait]
impl ApplicationHandler for SimpleApplicationHandler {
    async fn agent_chat_request(
        &self,
        request_message: AgentChatRequestMessage,
    ) -> anyhow::Result<AgentChatResponseMessage> {
        //
        let pre_prompt = if let Some(prompt) = &self.model_config.pre_prompt {
            prompt.clone()
        } else {
            String::from("")
        };

        tracing::debug!("{}", pre_prompt);
        //从应用配置文件中获取到模型的设置
        let app_model = if let Some(mc) =  &self.model_config.model{
            mc.clone()
        }else{
            WorkflowModelBuilder::default().build()?
        };
        //调用大模型，生成提示词
        let chain = SomeChainsBuilder::default()
            .build()?
            .get_chat_block_chain(
                vec![
                    PromptTemplateItemBuilder::default()
                        .role(ASSISTANT_ROLE_KEY)
                        .text(pre_prompt)
                        .build()?,
                    PromptTemplateItemBuilder::default()
                        .role(USER_ROLE_KEY)
                        .text(request_message.query)
                        .build()?,
                ],
                &app_model,
            )
            .await?;
        // tracing::debug!("{:?}", chain);
        let engine = SimpleWorkflowEngine::default();
        //执行
        let m_id = engine
            .run(
                chain,
                HashMap::new(),
                WorkflowEngineRunOptionsBuilder::default().build()?,
            )
            .await?;
        //获取结果
        let result = engine.result_with_timeout(&m_id, true, 60000_u64).await;
        match result {
            Ok(v) => {
                tracing::debug!("{:?}", v);
                if let Some(text) = v.outputs.get(&String::from("text")) {
                    match text {
                        serde_json::Value::String(t) => {
                            //
                            Ok(AgentChatResponseMessageBuilder::default()
                                .data(vec![AgentChatResponseMessageItemBuilder::default()
                                    .answer(t)
                                    .build()?])
                                .build()?)
                        }
                        _ => Err(anyhow::anyhow!("返回的结果不是字符串")),
                    }
                } else {
                    Err(anyhow::anyhow!("没有找到结果"))
                }
            }
            Err(err) => Err(anyhow::anyhow!("{}", err)),
        }
    }

    //
    async fn application_datasource(&self) -> anyhow::Result<Option<DataSource>> {
        //
        Ok(self.datasource.clone())
    }
}
